import {useEffect, useState} from 'react';
import {Button, Checkbox, Image, Input, message, Modal, Result, Slider} from "antd";
import {
    ClearOutlined,
    ExportOutlined,
    FilePdfOutlined,
    FolderOpenOutlined,
    FundViewOutlined,
    InstagramOutlined,
    MergeCellsOutlined
} from "@ant-design/icons";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
import pdfjs from "@bundled-es-modules/pdfjs-dist/build/pdf";
import {isProduction} from "../../../utils";

// 动态设置 pdf.worker.js 路径，兼容 loadFile 和 loadURL
if (isProduction()) {
    pdfjs.GlobalWorkerOptions.workerSrc = "./pdf.worker.js";
} else {
    pdfjs.GlobalWorkerOptions.workerSrc = "/pdf.worker.js";
}

export interface SourceImageType {
    imgData: string;
    imgName: string;
    isCheck: boolean;
}

function PdfToImg() {
    const [messageApi, contextHolder] = message.useMessage();

    const [sourceImages, setSourceImages] = useState([] as SourceImageType[]);
    const [imageRecord, setImageRecord] = useState([] as SourceImageType[]);
    const [pdfFilePath, setPdfFilePath] = useState('');
    const [saveDirPath, setSaveDirPath] = useState('');
    const [mergeImage, setMergeImage] = useState(true);
    const [pictureWatermark, setPictureWatermark] = useState('SlayingDragon'); // 默认水印文字
    const [pictureClarity, setPictureClarity] = useState(100); // 默认清晰度为100%

    const [responseBody, setResponseBody] = useState({
        open: false,
        status: 'success',
        title: '',
        content: '',
    });


    /**
     * 打开PDF文件选择对话框，选择PDF文件并解析，显示在预览框
     */
    const onOpenDialogSelectedPDF = async () => {
        const pdfFile = await window.native.openPdfDialog(['.pdf']);
        if (!pdfFile) {
            messageApi.error('未选择PDF文件或文件读取失败');
            return;
        }
        const {arrayBuffer, fileName, filePath} = pdfFile;
        if (!arrayBuffer || !fileName || !filePath) {
            messageApi.error('未选择PDF文件或文件读取失败');
            return;
        }

        // 设置PDF文件路径和保存目录
        setPdfFilePath(filePath);
        if (!saveDirPath) {
            setSaveDirPath(filePath.replace(fileName, ''));
        }

        // 解析PDF文件
        const loadingTask = pdfjs.getDocument(arrayBuffer);
        const pdf = await loadingTask.promise;

        for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
            const page = await pdf.getPage(pageNum);
            const viewport = page.getViewport({scale: 2});

            // 创建Canvas
            const canvas = document.createElement('canvas');
            canvas.width = viewport.width;
            canvas.height = viewport.height;
            const context = canvas.getContext('2d');

            // 渲染PDF页面到Canvas
            if (context) {
                await page.render({canvasContext: context, viewport}).promise;
            }

            const newImage = {
                imgData: canvas.toDataURL('image/jpeg', pictureClarity / 100.0), // 使用JPEG格式
                imgName: `${fileName.slice(0, fileName.lastIndexOf("."))}.p${pageNum}.jpg`,
                isCheck: true,
            };

            // 先缓存选择的图片
            setSourceImages((si) => [...si, newImage]);
        }
    }

    useEffect(() => {
        updatePreviewUI().then();
    }, [sourceImages, pictureWatermark, pictureClarity]);

    /**
     * 读取[sourceImages]缓存的图片记录，计算清晰度与加入水印，更新页面显示
     */
    const updatePreviewUI = async () => {
        // 1. 处理 sourceImages，生成带水印和清晰度的新图片
        const processedImages = await Promise.all(sourceImages.map(async (img) => {
            // 创建图片对象
            return new Promise<SourceImageType>((resolve) => {
                const image = new window.Image();
                image.onload = () => {
                    // 创建canvas
                    const canvas = document.createElement('canvas');
                    canvas.width = image.width;
                    canvas.height = image.height;
                    const ctx = canvas.getContext('2d');
                    if (ctx) {
                        // 绘制原图
                        ctx.drawImage(image, 0, 0);
                        // 添加水印（如有）
                        if (pictureWatermark) {
                            ctx.save();
                            ctx.translate(canvas.width / 2, canvas.height / 2);
                            ctx.rotate(-Math.PI / 4); // 45度
                            ctx.font = 'bold 36px Arial';
                            ctx.fillStyle = 'rgba(180,180,180,0.18)';
                            ctx.textAlign = 'center';
                            ctx.textBaseline = 'middle';
                            // 计算水印间距
                            const textWidth = ctx.measureText(pictureWatermark).width;
                            const stepX = (textWidth + 80) / 0.8;
                            const stepY = 80 / 0.8;
                            const drawWidth = Math.sqrt(canvas.width * canvas.width + canvas.height * canvas.height);
                            const drawHeight = drawWidth;
                            for (let dx = -drawWidth / 2; dx < drawWidth / 2; dx += stepX) {
                                for (let dy = -drawHeight / 2; dy < drawHeight / 2; dy += stepY) {
                                    ctx.fillText(pictureWatermark, dx, dy);
                                }
                            }
                            ctx.restore();
                        }
                    }
                    // 导出新图片（按清晰度）
                    const newImgData = canvas.toDataURL('image/jpeg', pictureClarity / 100);
                    resolve({
                        ...img,
                        imgData: newImgData,
                    } as SourceImageType);
                };
                image.src = img.imgData;
            });
        }));
        setImageRecord(processedImages);
    }

    const openDirectoryDialog = async () => {
        const dirPath = await window.native.selectDirectory();
        if (!dirPath) return;
        setSaveDirPath(dirPath);
    }

    // 合并图片为一张（纵向拼接，带灰色阴影边距）
    const mergeImages = async (images: { fileName: string, buffer: string }[]) => {
        // 1. 加载所有图片
        const loadedImages = await Promise.all(images.map(img =>
            new Promise<HTMLImageElement>((resolve) => {
                const image = new window.Image();
                image.onload = () => resolve(image);
                image.src = 'data:image/jpeg;base64,' + img.buffer;
            })
        ));
        // 2. 计算总高度和最大宽度
        const border = 20; // 边距宽度
        const gap = 10; // 图片间距
        const shadowOffset = 8; // 阴影偏移
        const totalHeight = loadedImages.reduce((sum: number, img) => sum + (img as HTMLImageElement).height + gap, -gap) + border * 2;
        const maxWidth = Math.max(...loadedImages.map(img => (img as HTMLImageElement).width)) + border * 2;
        // 3. 创建大canvas
        const canvas = document.createElement('canvas');
        canvas.width = maxWidth + shadowOffset;
        canvas.height = totalHeight + shadowOffset;
        const ctx = canvas.getContext('2d')!;
        // 4. 绘制背景
        ctx.fillStyle = '#f0f0f0'; // 灰色背景
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        // 5. 依次绘制图片（带阴影）
        let y = border;
        for (const img of loadedImages) {
            const image = img as HTMLImageElement;
            // 阴影
            ctx.save();
            ctx.shadowColor = 'rgba(0,0,0,0.18)';
            ctx.shadowBlur = 12;
            ctx.shadowOffsetX = shadowOffset;
            ctx.shadowOffsetY = shadowOffset;
            ctx.drawImage(image, border, y, image.width, image.height);
            ctx.restore();
            // 斜着45度满屏水印（规则排布，且与上一页错位，避免重叠）
            if (pictureWatermark) {
                ctx.save();
                ctx.translate(border + image.width / 2, y + image.height / 2);
                ctx.rotate(-Math.PI / 4); // 45度
                ctx.font = 'bold 50px Arial'; // 字体调大
                ctx.fillStyle = 'rgba(180,180,180,0.18)';
                ctx.textAlign = 'center';
                ctx.textBaseline = 'middle';
                // 计算水印间距
                const textWidth = ctx.measureText(pictureWatermark).width;
                const stepX = (textWidth + 80) / 0.8; // 密度降低到80%
                const stepY = 80 / 0.8; // 水平间距和垂直间距
                // 计算可覆盖区域
                const drawWidth = Math.sqrt(image.width * image.width + image.height * image.height);
                const drawHeight = drawWidth; // 保持正方形区域
                // 错位偏移量，保证每页水印不重叠
                const offsetX = (y / stepX) % stepX;
                const offsetY = (y / stepY) % stepY;
                for (let dx = -drawWidth / 2 + offsetX; dx < drawWidth / 2; dx += stepX) {
                    for (let dy = -drawHeight / 2 + offsetY; dy < drawHeight / 2; dy += stepY) {
                        ctx.fillText(pictureWatermark, dx, dy);
                    }
                }
                ctx.restore();
            }
            y += image.height + gap;
        }
        // 6. 导出图片
        return canvas.toDataURL('image/jpeg', pictureClarity / 100.0);
    };

    /**
     * 将选中的图片保存到用户指定的目录
     * 根据用户选择的合并选项，决定是单独保存每一页还是合并为一张图片
     * @returns {Promise<void>}
     */
    const onSaveImageToDirectory = async (): Promise<void> => {
        let images = imageRecord.filter((it) => it.isCheck).map((it) => {
            return {
                fileName: it.imgName,
                buffer: it.imgData.indexOf(',') !== -1 ? it.imgData.split(',')[1] : it.imgData, // base64
            };
        });

        if (!images || images.length <= 0) {
            messageApi.error('请先需要转换的页');
            return;
        }
        if (!saveDirPath) {
            messageApi.error('请先选择保存目录');
            return;
        }

        // 合并图片
        if (mergeImage) {
            const mergedDataUrl = await mergeImages(images);
            const mergedImage = {
                fileName: `merged-[${images.length}].jpg`,
                buffer: mergedDataUrl.split(',')[1],
            };
            images = [mergedImage]; // 替换为合并后的图片
        }

        // 3. 保存图片
        const result = await window.native.saveImage(saveDirPath, images);

        // 4. 处理结果
        if (result.success) {
            const failedFiles = result.results.filter(r => !r.success);
            if (failedFiles.length === 0) {
                setResponseBody({
                    ...responseBody,
                    open: true,
                    status: 'success',
                    title: '所有图片保存成功',
                    content: `所有图片已成功保存到：${saveDirPath}`,
                })
            } else {
                setResponseBody({
                    ...responseBody,
                    open: true,
                    status: 'warning',
                    title: '部分文件保存失败',
                    content: failedFiles.map(f => f.fileName).join('\n'),
                })
            }
        } else {
            messageApi.error(`保存失败：${result.error}`);
        }
    }

    const onClear = async () => {
        setImageRecord(() => []);
        setPdfFilePath(() => '');
        setSaveDirPath(() => '');
        setMergeImage(() => true);
        setPictureWatermark(() => '');
        setPictureClarity(() => 80);
        await messageApi.info('已清空所有记录');
    }

    return (
        <div style={{
            padding: '0 20px',
        }}>
            {/* 显示 message */}
            <div style={{zIndex: 999}}>
                {contextHolder}
            </div>
            {/* PDF预览区，网格展示 */}
            <div
                style={{
                    height: 'calc(100vh - 305px)', // 200px 可根据实际顶部和底部高度调整
                    overflowY: 'auto',
                    display: 'grid',
                    gridTemplateColumns: 'repeat(auto-fit, minmax(100px, auto))',
                    justifyContent: 'flex-start', // 左对齐关键属性
                    gap: '10px',
                    padding: '10px',
                    margin: '0 0 20px 0',
                    minHeight: '50vh',
                    border: '1px solid #ddd',
                    borderRadius: '6px',
                    zIndex: 900
                }}>

                <Image.PreviewGroup preview={{}}>
                    {imageRecord.map((it, index) => (
                        <div style={{
                            textAlign: 'center',
                            display: 'flex',
                            flexDirection: 'column',
                            alignItems: 'center'
                        }} key={it.imgName + index}>
                            <Image width={100} src={it.imgData} alt={it.imgName} style={{
                                border: '1px solid #ddd',
                                boxShadow: '0 2px 8px rgba(0,0,0,0.1)'
                            }}/>

                            <Checkbox checked={it.isCheck} onChange={(e) => {
                                e.stopPropagation();
                                const updatedRecord = [...imageRecord];
                                updatedRecord[index].isCheck = e.target.checked;
                                setImageRecord(updatedRecord);
                            }}/>
                        </div>
                    ))}
                </Image.PreviewGroup>
            </div>

            <div style={{position: "absolute", bottom: '0', left: '20px', right: '20px'}}>
                <div style={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'space-between',
                    padding: '5px 0'
                }}>
                    <Button icon={<FilePdfOutlined/>} onClick={onOpenDialogSelectedPDF}>选择PDF</Button>
                    <span>&nbsp;&nbsp;</span>
                    <Input value={pdfFilePath} variant="filled"
                           placeholder={'点击按钮选择文档，多个文件可以多次选择'}/>
                </div>
                <div style={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'space-between',
                    padding: '5px 0'
                }}>
                    <Button icon={<FolderOpenOutlined/>} onClick={openDirectoryDialog}>保存目录</Button>
                    <span>&nbsp;&nbsp;</span>
                    <Input value={saveDirPath} onChange={(e) => {
                        setSaveDirPath(e.target.value)
                    }} placeholder={'选择输出图片的目录'}/>
                </div>
                <div
                    style={{display: 'flex', alignItems: 'center', justifyContent: 'flex-start', padding: '5px 0'}}>
                    <Button icon={<MergeCellsOutlined/>} color="default" variant="text">合并图片</Button>
                    <span>&nbsp;&nbsp;</span>
                    <Checkbox checked={mergeImage} onChange={(e) => {
                        setMergeImage(e.target.checked);
                    }}>{mergeImage ? '合并为一张输出' : '单独输出每一页'}</Checkbox>
                </div>
                <div style={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'space-between',
                    padding: '5px 0'
                }}>
                    <Button icon={<InstagramOutlined/>} color="default" variant="text">图片水印</Button>
                    <span>&nbsp;&nbsp;</span>
                    <Input value={pictureWatermark} onChange={(e) => setPictureWatermark(e.target.value)}
                           placeholder={'输入水印文字'} allowClear/>
                </div>
                <div style={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'space-between',
                    padding: '5px 0'
                }}>
                    <Button icon={<FundViewOutlined/>} color="default" variant="text">图清晰度</Button>
                    <span>&nbsp;&nbsp;</span>
                    <div style={{
                        flexGrow: 1,
                        display: 'inline-flex',
                        alignItems: 'center',
                        justifyContent: 'space-between'
                    }}>
                        <Slider style={{flexGrow: 1}} step={10} value={pictureClarity}
                                onChange={v => setPictureClarity(v)}
                                min={50}/>
                        <span style={{
                            width: 'auto',
                            marginLeft: 10,
                            color: '#1677ff',
                            fontSize: '14px'
                        }}>导出清晰度: {pictureClarity}%</span>
                    </div>
                </div>
            </div>

            <div style={{position: "fixed", right: '20px', top: '0px', zIndex: 9999}}>
                <div style={{
                    display: 'flex',
                    alignItems: 'center',
                    justifyContent: 'space-between',
                    padding: '10px 0'
                }}>
                    <Button type="primary" disabled={imageRecord.length <= 0} danger icon={<ClearOutlined/>}
                            onClick={() => onClear()}>清空</Button>
                    <span>&nbsp;&nbsp;</span>
                    <Button type="primary" disabled={imageRecord.length <= 0} icon={<ExportOutlined/>}
                            onClick={onSaveImageToDirectory}>转换</Button>
                </div>
            </div>

            <Modal open={responseBody.open} footer={null}>
                <Result
                    // status={responseBody.status}
                    status={responseBody.status === 'success' ? 'success' : 'warning'}
                    title={responseBody.title}
                    subTitle={responseBody.content}
                    extra={[
                        <Button
                            type="primary"
                            key="ok"
                            disabled={responseBody.status !== 'success'}
                            onClick={async () => {
                                await window.native.openSavePath(saveDirPath);
                            }}>
                            打开保存目录
                        </Button>,
                        <Button key="no" onClick={() => {
                            setResponseBody({...responseBody, open: false})
                        }}>
                            关闭
                        </Button>,
                    ]}
                />
            </Modal>

        </div>
    );
}

export default PdfToImg;
